﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using TiaoTiaoCode.BasicDbCore;
using TiaoTiaoCode.Quartzer;
using TiaoTiaoCode.Quartzer.Entities;
using TiaoTiaoCode.QuartzUI.Models;

namespace TiaoTiaoCode.QuartzUI.ViewModels
{
    public class MainViewModel : ObservableObject
    {
        #region 字段

        readonly static ISqlSugarClient _scope = DbFramework.Scope;

        #endregion

        #region 属性

        private ObservableCollection<JobDetail>? jobDetails;

        public ObservableCollection<JobDetail>? JobDetails
        {
            get { return jobDetails; }
            set { SetProperty(ref jobDetails, value); }
        }

        private string? cronExpression;

        public string? CronExpression
        {
            get { return cronExpression; }
            set { SetProperty(ref cronExpression, value); }
        }

        private string? jobName;

        public string? JobName
        {
            get { return jobName; }
            set { SetProperty(ref jobName, value); }
        }

        private string? groupCode;

        public string? GroupCode
        {
            get { return groupCode; }
            set { SetProperty(ref groupCode, value); }
        }

        private ObservableCollection<Type>? jobTypes;

        public ObservableCollection<Type>? JobTypes
        {
            get { return jobTypes; }
            set { SetProperty(ref jobTypes, value); }
        }

        private Type? selectedType;

        public Type? SelectedType
        {
            get { return selectedType; }
            set { SetProperty(ref selectedType, value); }
        }

        private string? schedularState;

        public string? SchedularState
        {
            get { return schedularState; }
            set { SetProperty(ref schedularState, value); }
        }

        #endregion

        #region 命令

        #region Schedular

        IRelayCommand? startSchedularCommand;
        IRelayCommand? stopSchedularCommand;
        IRelayCommand? clearSchedularCommand;

        public IRelayCommand StartSchedularCommand => startSchedularCommand ??= new RelayCommand(StartSchedular);
        public IRelayCommand StopSchedularCommand => stopSchedularCommand ??= new RelayCommand(StopSchedular);
        public IRelayCommand ClearSchedularCommand => clearSchedularCommand ??= new RelayCommand(ClearSchedular);

        #endregion

        #region Job

        IRelayCommand? startJobCommand;
        IRelayCommand? pauseJobCommand;
        IRelayCommand? deleteJobCommand;
        IRelayCommand? addJobCommand;

        public IRelayCommand AddJobCommand => addJobCommand ??= new RelayCommand(AddJob);
        public IRelayCommand StartJobCommand => startJobCommand ??= new RelayCommand<string?>(StartJob);
        public IRelayCommand PauseJobCommand => pauseJobCommand ??= new RelayCommand<string?>(PauseJob);
        public IRelayCommand DeleteJobCommand => deleteJobCommand ??= new RelayCommand<string?>(DeleteJob);

        #endregion

        IRelayCommand? startAllCommand;
        IRelayCommand? stopAllCommand;
        IRelayCommand? cronCommand;

        public IRelayCommand StartAllCommand => startAllCommand ??= new RelayCommand(StartAll);
        public IRelayCommand StopAllCommand => stopAllCommand ??= new RelayCommand(StopAll);
        public IRelayCommand CronCommand => cronCommand ??= new RelayCommand(LinkCron);

        #endregion

        public MainViewModel()
        {
            LoadJobs();

            RefreshJobList();
        }

        #region 命令实现

        #region  Schedular

        void StartSchedular()
        {
            TiaoTiaoQuartz.Start();
            SchedularState = "LightGreen";
        }

        void StopSchedular()
        {
            TiaoTiaoQuartz.Stop();
            SchedularState = "Transparent";
        }

        void ClearSchedular()
        {
            TiaoTiaoQuartz.Clear();
        }

        #endregion

        #region Job

        void AddJob()
        {
            TiaoTiaoQuartz.AddJob(SelectedType!, JobName!, GroupCode!, CronExpression!).Wait();
            RefreshJobList();
        }

        void StartJob(string? id)
        {
            TiaoTiaoQuartz.StartJob(new List<string> { id! });
            RefreshJobList();            
        }

        void PauseJob(string? id)
        {
            TiaoTiaoQuartz.PauseJob(new List<string> { id! });
            RefreshJobList();
        }

        void DeleteJob(string? id)
        {
            TiaoTiaoQuartz.DeleteJob(new List<string> { id! });
            RefreshJobList();
        }

        #endregion

        void StartAll()
        {
            var ids = JobDetails?.Select(t => t.Id).ToList();
            if (ids == null || ids.Count <= 0) return;

            TiaoTiaoQuartz.StartJob(ids!);
            RefreshJobList();
        }

        void StopAll()
        {
            var ids = JobDetails?.Select(t => t.Id).ToList();
            if (ids == null || ids.Count <= 0) return;

            TiaoTiaoQuartz.PauseJob(ids!);
            RefreshJobList();
        }

        void LinkCron()
        {
            Process.Start(new ProcessStartInfo("cmd", $"/c start http://cron.ciding.cc/") { CreateNoWindow = true });
        }

        #endregion

        #region 数据库

        async void RefreshJobList()
        {
            var data = await _scope.Queryable<QuartzJobs>().ToListAsync();

            JobDetails?.Clear();
            JobDetails = new ObservableCollection<JobDetail>(
                data.Select(t => new JobDetail
                {
                    Id = t.Id,
                    JobName = t.JobName,
                    JobCode = t.JobCode,
                    JobStatus = t.JobStatus,
                    Cron = t.CronExpression
                })
                );
        }

        #endregion

        #region

        void LoadJobs()
        {
            var types = Assembly.GetEntryAssembly()!.GetTypes().Where(t => t.GetInterface("IJob") != null).ToList();

            JobTypes?.Clear();
            JobTypes = new ObservableCollection<Type>(types);
        }

        #endregion
    }
}
